package com.assistant.ai;

import ch.qos.logback.core.subst.Token;
import com.assistant.core.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import com.google.gson.Gson;
import com.google.gson.JsonObject;


/**
 * @author Anyang
 * @version 1.0.0
 * @date 2025/10/25 05:10:50
 * @description 语音合成模块
 */
public class TTSModule {
    private static final Logger logger = LoggerFactory.getLogger(TTSModule.class);
    private final HttpClient httpClient;
    private final Gson gson;
    /**
     * 存储公有云 Access Token，供 TTS/STT 共享使用
      */
    private String publicCloudAccessToken;

    public TTSModule() {
        this.httpClient = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_2)
                .connectTimeout(Duration.ofSeconds(10))
                .build();
        this.gson = new Gson();

        // 在初始化时获取公有云 Access Token
        try {
            this.publicCloudAccessToken = fetchNewAccessToken();
        } catch (Exception e) {
            logger.error("TTSModule 初始化失败：无法获取百度 Access Token。", e);
        }
    }

    /**
     * 【新增】获取公有云 Access Token 的方法，供 STTModule 使用
     */
    public String getAccessToken() {
        return this.publicCloudAccessToken;
    }

    /**
     * 使用 BAIDU_API_KEY/SECRET_KEY 获取临时的 Access Token。
     */
    private String fetchNewAccessToken() {
        logger.info("【公有云鉴权】1. 正在使用通用 Key/Secret 换取 Access Token...");

        if (Config.BAIDU_API_KEY == null || Config.BAIDU_SECRET_KEY == null || Config.BAIDU_API_KEY.isEmpty() || Config.BAIDU_SECRET_KEY.isEmpty()) {
            logger.error("【公有云鉴权】错误：BAIDU_API_KEY 或 BAIDU_SECRET_KEY 未配置。");
            return null;
        }

        String authUrl = String.format(
                "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s",
                URLEncoder.encode(Config.BAIDU_API_KEY, StandardCharsets.UTF_8),
                URLEncoder.encode(Config.BAIDU_SECRET_KEY, StandardCharsets.UTF_8)
        );

        try {
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(authUrl))
                    .header("Content-Type", "application/json")
                    .timeout(Duration.ofSeconds(5))
                    .POST(HttpRequest.BodyPublishers.noBody())
                    .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

            if (response.statusCode() == 200) {
                JsonObject jsonResponse = gson.fromJson(response.body(), JsonObject.class);
                String token = jsonResponse.get("access_token").getAsString();
                logger.info("【公有云鉴权】2. Access Token 获取成功，有效期由百度控制。");
                return token;
            } else {
                logger.error("【公有云鉴权】Access Token 获取失败，状态码: {}, 响应体: {}", response.statusCode(), response.body());
                return null;
            }
        } catch (Exception e) {
            logger.error("【公有云鉴权】网络请求失败", e);
            return null;
        }
    }


    /**
     * 合成文本并播放。
     * @param text 要合成的文本
     */
    public void speak(String text) {
        if (text == null || text.trim().isEmpty() || this.publicCloudAccessToken == null) {
            if (this.publicCloudAccessToken == null) {
                logger.error("【TTS流程】跳过播放：Access Token 无效。");
            }
            return;
        }

        logger.info("【TTS流程】3. 向百度 TTS API 发送请求 (请求 16k PCM 格式)...");

        // 【BUG修复 1】将 aue=3 (MP3) 修改为 aue=4 (16k PCM)，必须与 playPcmAudio 方法的格式 (16k PCM) 匹配。
        String ttsUrl = Config.BAIDU_TTS_URL + "?tex=" + URLEncoder.encode(text, StandardCharsets.UTF_8) +
                "&tok=" + this.publicCloudAccessToken +
                "&cuid=voice_assistant&ctp=1&vol=5&per=4&spd=5&pit=5&lan=zh&aue=4";

        try {
            // 2. 发送请求
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(ttsUrl))
                    .header("Accept", "audio/pcm") // 期望 PCM
                    .timeout(Duration.ofSeconds(10))
                    .POST(HttpRequest.BodyPublishers.noBody())
                    .build();

            HttpResponse<byte[]> response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());

            // 3. 处理响应
            if (response.statusCode() == 200) {

                // 【BUG修复 2】检查返回的 Content-Type。如果不是 audio，说明是 JSON 错误。
                String contentType = response.headers().firstValue("Content-Type").orElse("");
                byte[] responseData = response.body();

                if (contentType.contains("audio/")) {
                    // 成功获取音频
                    logger.info("【TTS流程】4. TTS API 返回 {} 字节音频数据 ({})，准备播放。", responseData.length, contentType);
                    playPcmAudio(responseData);
                } else {
                    // 收到的是 JSON 错误（例如 token 过期、文本内容非法等）
                    String errorBody = new String(responseData, StandardCharsets.UTF_8);
                    logger.error("【TTS流程】TTS API 调用成功（200）但返回了错误 JSON ({} 字节): {}", responseData.length, errorBody);
                }

            } else {
                logger.error("【TTS流程】TTS API 调用失败，状态码: {}, 响应体: {}", response.statusCode(), new String(response.body(), StandardCharsets.UTF_8));
            }

        } catch (Exception e) {
            logger.error("【TTS流程】网络或IO错误", e);
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 播放 PCM 格式的音频数据（16kHz, 16bit, 单声道）。
     */
    private void playPcmAudio(byte[] audioBytes) {
        // ... (此方法逻辑正确，保持不变)
        if (audioBytes == null || audioBytes.length == 0) {
            logger.warn("TTS 音频数据为空，跳过播放。");
            return;
        }

        // 百度 TTS 返回的是原始 PCM 裸数据，格式为 16kHz, 16bit, Mono
        float sampleRate = 16000;
        int sampleSizeInBits = 16;
        int channels = 1;
        boolean signed = true;
        boolean bigEndian = false;
        AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
        int frameSize = (sampleSizeInBits / 8) * channels;
        float frameRate = sampleRate;

        try {
            // 2. 创建正确的 AudioFormat
            AudioFormat format = new AudioFormat(
                    encoding,
                    sampleRate,
                    sampleSizeInBits,
                    channels,
                    frameSize,
                    frameRate,
                    bigEndian
            );

            // 3. 将原始字节流封装到正确的 AudioInputStream 中
            try (AudioInputStream audioInputStream = new AudioInputStream(
                    new ByteArrayInputStream(audioBytes), format, audioBytes.length / format.getFrameSize())) {

                // 4. 开始播放
                try (SourceDataLine line = AudioSystem.getSourceDataLine(format)) {
                    line.open(format);
                    line.start();
                    logger.info("【TTS流程】5. 开始播放TTS音频，格式: PCM 16kHz。");

                    int bytesRead;
                    byte[] buffer = new byte[4096];
                    while ((bytesRead = audioInputStream.read(buffer)) != -1) {
                        line.write(buffer, 0, bytesRead);
                    }
                    line.drain();
                    line.stop();
                    logger.info("【TTS流程】6. TTS音频播放完成");
                }
            }
        } catch (Exception e) {
            logger.error("【TTS播放错误】音频播放时发生错误: {}", e.getMessage(), e);
        }
    }
}